/**
 * 
 */
package cn.mibcxb.java.dolphin.client;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.LinkedList;

import cn.mibcxb.java.dolphin.common.Commons;
import cn.mibcxb.java.dolphin.common.DolphinData;
import cn.mibcxb.java.dolphin.common.Status;
import cn.mibcxb.java.dolphin.exception.DolphinException;

/**
 * @author CXB
 * 
 */
public class Sender {
	private static Sender mSender = null;
	private static boolean mFlag = true;
	private static LinkedList<DolphinData> dataQueue = new LinkedList<DolphinData>();
	private DolphinConsole console = null;

	private Sender(DolphinConsole console) {
		this.console = console;
	}

	private Thread mRunner = new Thread() {

		@Override
		public void run() {
			DatagramSocket ds = null;
			DolphinData data = null;
			try {
				ds = new DatagramSocket();
				while (mFlag) {
					if (dataQueue.size() < 1) {
						synchronized (mRunner) {
							mRunner.wait();
						}
					}
					data = dataQueue.pollFirst();
					Status status = Commons.verifyDolphinData(data);
					if (Status.OK == status) {
						byte[] buffer = DolphinData.transform2Byte(data);
						if (null != buffer) {
							DatagramPacket packet = new DatagramPacket(buffer,
									buffer.length, data.getToAddr(),
									Commons.MSG_PORT);
							ds.send(packet);
						}
					} else {
						console.printMessage(Commons.getErrorMessage(status));
					}
					// console.printMessage("Sender : success");
					// console.printPromt(console.getmPrompt());
				}
			} catch (SocketException e) {
				e.printStackTrace();
			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				if (mFlag) {
					e.printStackTrace();
				}
			} catch (DolphinException e) {
				e.printStackTrace();
			} finally {
				if (null != ds) {
					ds.close();
				}
			}
		}

	};

	public static Sender getInstance(DolphinConsole console) {
		if (null == mSender) {
			mSender = new Sender(console);
		}
		return mSender;
	}

	public void start() {
		mRunner.start();
	}

	public void stop() {
		mFlag = false;
		if (null != mRunner) {
			mRunner.interrupt();
		}
	}

	public boolean isAlive() {
		return null != mRunner && mRunner.isAlive();
	}

	public Status send(DolphinData data) {
		console.printMessage("Sender : send + " + data.getCmd());
		Status status = Status.OK;
		if (null != mRunner) {
			dataQueue.add(data);
			synchronized (mRunner) {
				mRunner.notify();
			}
		} else {
			status = Status.NO_THREAD;
		}
		return status;
	}
}
